package com.crowntit.types.design.framework.link.model2.chain;


import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@NoArgsConstructor
public class LinkedList<E> implements ILink<E>{

    private String name;

    transient int size = 0;

    transient Node<E> first;

    transient Node<E> last;

    public LinkedList(String name) {
        this.name = name;
    }

    boolean linkFirst(E e){
        final Node<E> oldFirst = first;
        final Node<E> node = new Node<>(e, first, null);
        first = node;
        if (oldFirst != null)
            oldFirst.prev = node;
        else
            last = node;
        size++;

        return true;
    }

    boolean linkLast(E e){
        final Node<E> oldLast = last;
        final Node<E> node = new Node<>(e, oldLast, null);
        last = node;
        if (oldLast != null)
            oldLast.next = node;
        else
            first = node;
        size++;

        return true;
    }

    @Override
    public boolean add(E e) {
        return linkLast(e);
    }

    @Override
    public boolean addFirst(E e) {
        return linkFirst(e);
    }

    @Override
    public boolean addLast(E e) {
        return linkLast(e);
    }

    @Override
    public boolean remove(int index) {
        Node<E> target = first;
        for (int i = 0; i < index && target != null; i++) {
            target = target.next;
        }
        if (target == null)
            return false;

        Node<E> prev = target.prev;
        Node<E> next = target.next;
        prev.next = next;
        if (next != null)
            next.prev = prev;
        return true;
    }

    @Override
    public E get(int index) {
        Node<E> target = first;
        for (int i = 0; i < index && target != null; i++) {
            target = target.next;
        }
        if (target == null)
            return null;

        return target.item;
    }

    @Override
    public void printLinkList() {
        System.out.println("printLinkList example");
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    protected static class Node<E>{
        E item;

        Node<E> next;

        Node<E> prev;
    }

    public String getName() {
        return name;
    }
}
